package processing.test.mechaapp;
//game;

public class Molecule {
	//These int counts are what the molecules will use to compare each other with
	public int count = 0;
	public int oxygenCount = 0;
	public int hydrogenCount = 0;
	public int carbonCount = 0;
	public int nitrogenCount = 0;
	
	//This is the top of the double linked list that will contain a
	//REFFERENCE to each atom that is currently in this molecule.
	public AtomNode top;
	
	//is this molecule complete or not?
	//public boolean isComplete;
	
	public Molecule(Atom element){
		top = new AtomNode(element);
		//isComplete = false;

		updateCount(element,1);
	}
	
	public Molecule(){
		top = null;
		//isComplete = false;
	}	
	
	//order is not preserved in the molecules as they are being built!!
	//this method functions as a stack sort of -jt
	public void bondToMolecule(Atom element){
		if(this == element.molecule) return;
		AtomNode tempNode = element.molecule.top;
        AtomNode tempTop = tempNode;
        
        //combine the counts of both molecules. has to be placed before the molecule
        //references change!
        updateCount(element.molecule);
        
        //changes a the reference of atom's molecule in the old molecules
        //to the new one (this)
        //also traverses to the bottom of the other molecules linked list
        element.molecule = this;
        while(tempNode.getPrev() != null){
                tempNode = tempNode.getPrev();
                tempNode.getElement().molecule = this;
        }
        
        //puts the stack ontop of this one
        top.setNext(tempNode);
        tempNode.setPrev(top);
        
        //reassigns the top of this stack to the top of the old stack
        top = tempTop;
	}
	
	
	//breaks the current atom from the target atoms molecule
	//returns a reference to the newly created molecule - jt
	public Molecule breakFromMolecule(Atom current, Atom target){
		Molecule tempMolecule;
		//if number of bonds = 1 then that means the atoms is
		//at the "edge" of a molecule, and wont split up the current molecule
		//into fewer smaller ones.		
		if(current.numBonds == 1){
			breakNode(current);
			
			//The last step is to create a new molecule for the current atom and 
			//add the current atom into it (just like when the atom was first created)
			tempMolecule = new Molecule(current);
			current.molecule = tempMolecule;
		}
		//if the number of bonds is greater then 1, then a new sub molecule will be made
		else{
			tempMolecule = new Molecule();
			current.isVisited = true;
			newSubMolecule(target, tempMolecule);
			AtomNode temp = tempMolecule.top;
			
			while(temp != null){
				top.getElement().isVisited = false;
				temp = temp.getPrev();
			}
			current.isVisited = false;
		}
		
		return tempMolecule;
	}
	
	//recurses through all of targets's bonds and removes the atoms from this molecule
	//into the new molecule that has been passes in the parameter -jt
	private void newSubMolecule(Atom target, Molecule molecule){
		target.isVisited = true;
		
		for(int i=0; i<target.bonds.length; i++)
			if(target.bonds[i] != null && !target.bonds[i].isVisited)
				newSubMolecule(target.bonds[i],molecule);

		AtomNode temp;
		if(molecule.top == null){
			temp = breakNode(target);
			temp.setNext(null);
			temp.setPrev(null);
			molecule.top = temp;
		}else{
			temp = breakNode(target);
			temp.setNext(null);
			temp.setPrev(molecule.top);
			molecule.top.setNext(temp);
			molecule.top = temp;
		}
		
		molecule.updateCount(temp.getElement(), 1);		
		target.molecule = molecule;
	}
	
	//finds the node that is equal to current and removes it from
	//the molecule, then return the AtomNode it removed -jt
	private AtomNode breakNode(Atom current){
		AtomNode temp = top;
		
		while(temp != null){
			if(temp.getElement() == current){
				if(temp.getPrev() != null)
					temp.getPrev().setNext(temp.getNext());
				if(temp.getNext() != null)
					temp.getNext().setPrev(temp.getPrev());
				if(temp == top)
					top = temp.getPrev();
				
				updateCount(current,-1);
				return temp;
			}
			temp = temp.getPrev();
		}
		
		return null;
	}
	
	//This method will be used to compare two molecules together to
	//see if they contain the same number of atoms, since thats all that matters -jt
	public boolean compareTo(Molecule molecule){
		//should we only be comparing complete molecules?
		//if not just delete this next statement
		if(!checkCompleteness() || !molecule.checkCompleteness()) return false;
		
		if(hydrogenCount != molecule.hydrogenCount) return false;
		if(carbonCount != molecule.carbonCount) return false;
		if(nitrogenCount != molecule.nitrogenCount) return false;
		if(oxygenCount != molecule.oxygenCount) return false;
		
		return true;
	}
	
	
	//Determines if this molecule is complete then returns true if it is
	//false otherwise
	//IE: if every single atom in this molecule has all its bonds filled
	public boolean checkCompleteness(){
		AtomNode tempNode = top;
		
		while(tempNode != null){
			if(tempNode.getElement().numBonds != tempNode.getElement().maxBonds)
				return false;
			
			tempNode = tempNode.getPrev();
		}
		
		return true;
	}
	
	public void eraseMolecule(Atom[][] grid, float sz){
		int i, j;
		float x, y;
		Atom temp;
		
		while(top != null){
			temp = top.getElement();
			i = temp.ith;
			j = temp.jth;
			x = temp.xChord;
			y = temp.yChord;
			
			grid[i][j] = new blankAtom(x, y, i, j);
			top = top.getPrev();
		}
	}
	
	//this method determines which atom is which and adjusts the count
	//accordingly
	private void updateCount(Atom atom, int num){
		if(atom instanceof Oxygen)
			oxygenCount+=num;
		else if(atom instanceof Carbon)
			carbonCount+=num;
		else if(atom instanceof Hydrogen)
			hydrogenCount+=num;
		else if(atom instanceof Nitrogen)
			nitrogenCount+=num;
		
		count+=num;
	}
	
	private void updateCount(Molecule molecule){
		count += molecule.count;
		oxygenCount += molecule.oxygenCount;
		hydrogenCount += molecule.hydrogenCount;
		carbonCount += molecule.carbonCount;
		nitrogenCount += molecule.nitrogenCount;
	}
	
	//For debugging
		public String toString(){		
			return "OxygenCount = "+oxygenCount+"     HydrogenCount = "+hydrogenCount+"     CabrbonCount = "+carbonCount+
					"     NitrogenCount = "+nitrogenCount+"\nCount = "+count+"\n";
		}

}
